//dom相关操作工具类
function getStyle(el: HTMLElement, attr: string) {
  const style = getComputedStyle(el);
  return style.getPropertyValue(attr);
}
//获取元素的纵坐标
function getTop(el: HTMLElement, pNode?: HTMLElement) {
  let offset = el.offsetTop;
  const offsetParent = el.offsetParent as HTMLElement;
  if (pNode && offsetParent === pNode) return offset;
  if (offsetParent !== null) {
    offset += getTop(offsetParent, pNode);
  }
  return offset;
}
//获取元素的横坐标
function getLeft(el: HTMLElement, pNode?: HTMLElement) {
  let offset = el.offsetLeft;
  const offsetParent = el.offsetParent as HTMLElement;
  if (pNode && offsetParent === pNode) return offset;
  if (offsetParent != null) offset += getLeft(offsetParent, pNode);
  return offset;
}
const DomUtil = {
  getStyle,
  appendHTML(el: HTMLElement, htmlStr: string) {
    const div = document.createElement("div");
    const fragment = document.createDocumentFragment();
    div.innerHTML = htmlStr;
    const nodes = div.childNodes;
    let first;
    for (let i = 0, length = nodes.length; i < length; i++) {
      const node = nodes[i].cloneNode(true);
      if (!first) {
        first = node;
      }
      fragment.appendChild(node);
    }
    el.appendChild(fragment);
    return first;
  },
  //向上遍历目标元素的所有祖先元素 直到找到class含vali或者vali()返回true并返回
  findTargetParent(el: HTMLElement | Node | null, vali: string | Function) {
    const type = typeof vali;
    while (el) {
      if (type == "function") {
        if ((vali as Function)(el)) {
          return el;
        }
      } else if (type == "string") {
        const classList = (el as HTMLElement).classList;
        if (classList) {
          const clsArr = (vali as string).split(",");
          // eslint-disable-next-line no-cond-assign
          for (let i = 0, ii; (ii = clsArr[i++]); ) {
            if (classList.contains(ii)) {
              return el;
            }
          }
        }
      } else {
        throw new Error("vali参数非法");
      }
      const tagName = (el as HTMLElement).tagName;
      if (typeof tagName == "string" && tagName.toLowerCase() === "body") {
        return null;
      }
      el = el.parentNode;
    }
    return null;
  },
  offsetEl(el: HTMLElement, pNode?: HTMLElement) {
    return {
      left: getLeft(el, pNode),
      top: getTop(el, pNode),
    };
  },
  getElBox(el: HTMLElement) {
    const offset = this.offsetEl(el);
    return {
      left: offset.left,
      top: offset.top,
      width: el.offsetWidth,
      height: el.offsetHeight,
    };
  },
  bodyHasScrollbar() {
    return document.body.scrollHeight > window.innerHeight;
  },
  getScrollbarWidth() {
    const scrollDiv = document.createElement("div");
    scrollDiv.style.cssText =
      "width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;";
    document.body.appendChild(scrollDiv);
    const scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
    document.body.removeChild(scrollDiv);
    DomUtil.getScrollbarWidth = function () {
      return scrollbarWidth;
    };
    return scrollbarWidth;
  },
  on(
    el: HTMLElement | Document | Window,
    event: string,
    handler: EventListenerOrEventListenerObject,
    capture = false
  ) {
    if (el && event && handler) {
      el.addEventListener(event, handler, capture);
    }
  },
  off(
    el: HTMLElement | Document | Window,
    event: string,
    handler: EventListenerOrEventListenerObject,
    capture = false
  ) {
    if (el && event && handler) {
      el.removeEventListener(event, handler, capture);
    }
  },
  once(
    el: HTMLElement | Document | Window,
    event: string,
    handler: EventListener
  ) {
    if (el && event && handler) {
      const fn = function (e: Event) {
        handler.call(el, e);
        DomUtil.off(el, event, fn);
      };
      DomUtil.on(el, event, fn);
    }
  },
  getTextWidth(text: string | number, style?: string) {
    const span = document.createElement("span");
    if (style) {
      span.setAttribute("style", style);
    }
    span.innerText = text + "";
    document.body.appendChild(span);
    const width = span.offsetWidth;
    document.body.removeChild(span);
    return width;
  },
  /**
   * 获取绝对定位元素在父元素4个边缘外定位时，与body边缘的距离
   * @param el 绝对定位元素
   * @param parentEl 父元素
   * @returns
   */
  getAroundElToBody(el: HTMLElement, parentEl: HTMLElement) {
    const box = this.getElBox(el);
    const pBox = this.getElBox(parentEl);
    const bodyHeight = document.body.offsetHeight;
    const bodyWidth = document.body.offsetWidth;
    return {
      top: pBox.top - box.height,
      bottom: bodyHeight - (pBox.top + pBox.height + box.height),
      left: pBox.left - box.width,
      right: bodyWidth - (pBox.left + pBox.width + box.width),
    };
  },
};
export default DomUtil;
